<!--
* @Version V1.0
* @Project: MGS平台10.1 All rights Reserved, Designed By www.supermap.com
* @Title: 三维地图
* @Description: 三维地图 组件
* @Author: wanghan
* @Date: Created in 2021-03-15 14:22:49
* @Copyright: 2021 www.supermap.com Inc. All rights reserved.
* 注意：本内容仅限于北京超图信息技术有限公司内部传阅，禁止外泄以及用于其他的商业目
-->
<template>
    <div ref="map" class="mgs-c-view" v-once />
</template>

<script lang="ts">
import type { View } from 'types'

import { Component, Prop, Mixins, Watch } from 'vue-property-decorator'

import ViewMixin from './view-mixin'
import LayerMixin from './layer-mixin'
import CLayerMixin from './cesium-layer-mixin'
import DrawMixin from './draw-mixin'
import InteractionMixin from './interaction-mixin'
import PluginMixin from '@/mixins/plugin-mixin'

import * as Cesium from 'Cesium'
import { getViewCtrl, getView, compareView } from '@/utils/view'

//地图服务默认配置
const mapDefaultOptions = {
    infoBox: false,
    navigation: false,
    sceneModePicker: false,
    // 选中后绿框
    selectionIndicator: false,
    // 默认打开贴地
    clampToGround: true,
    // 截图相关参数
    contextOptions: {
        webgl: {
            alpha: true,
            depth: true,
            stencil: true,
            antialias: true,
            premultipliedAlpha: true,
            //通过canvas.toDataURL()实现截图需要将该项设置为true
            preserveDrawingBuffer: true,
            failIfMajorPerformanceCaveat: true,
        },
    },
}

@Component
export default class MgsCView extends Mixins(
    ViewMixin,
    LayerMixin,
    CLayerMixin,
    DrawMixin,
    InteractionMixin,
    PluginMixin
) {
    // 读取指定目录插件
    readonly PluginClazzes = require.context('./plugins/', false, /.ts$/)

    // 地图类型
    readonly MapType = '3D'

    /**
     * 是否显示superMap Logo
     */
    @Prop({ type: Boolean, default: false })
    logo!: boolean

    /**
     * 地图初始化参数（详细请看 `Cesium.Viewer` 构造参数）
     */
    @Prop({ type: Object, default: () => ({}) })
    options!: any

    /**
     * 图幅中心点和缩放（支持sync参数）
     */
    @Prop(Object)
    view?: View
    private viewDirty = true

    mounted() {
        this.$nextTick(() => {
            const map = new Cesium.Viewer(
                this.$refs.map as HTMLElement,
                Object.assign({}, mapDefaultOptions, this.options)
            )
            ;(map as any).vc = getViewCtrl(map, { scale: this.scale })
            ;(map as any)._isVue = true
            this.map = map as any

            // 清空默认底图
            map.imageryLayers.removeAll()

            // 初始化draw图层
            this._initDrawMixin(map)
            // 要素选择器
            this._initInteractionMixin(map)

            // 同步地图事件
            this.syncEvents(map)

            // 设置视图
            this.viewWatcher(this.view)

            // 加载插件
            this._loadPlugins()

            // 去除logo
            if (!this.logo) {
                const logo = this.$el.querySelector('.cesium-viewer-bottom')
                logo && logo.remove()
            }

            /**
             * 地图初始化完毕
             */
            this.$emit('onMapInited', this)
        })
    }

    beforeDestroy() {
        try {
            this.map.destroy()
        } catch (error) {
            // do nothing
        } finally {
            this.map = undefined as any
        }
    }

    @Watch('view', { deep: true })
    viewWatcher(nvl?: View) {
        // 不存在视图
        if (!this.map || !nvl) return

        // 视图不一致
        if (this.viewDirty && compareView(nvl, getView(this.map))) {
            this.viewDirty = false
            this.zoom2Centoid(nvl.center, { zoom: nvl.zoom, duration: 0 })
        }
    }

    private syncEvents(map: Cesium.Viewer) {
        map.camera.moveEnd.addEventListener(() => {
            /**
             * 缩放完成事件
             */
            this.$emit('onZoomEnd')

            if (!this.viewDirty) {
                this.viewDirty = true
                return
            }
            // 更新中心点 同步视图
            const view = getView(this.map)
            if (compareView(this.view, view)) {
                this.viewDirty = false
                this.$emit('update:view', view)
                this.$nextTick(() => (this.viewDirty = true))
            }
        })
    }
}
</script>

<docs>
## Demo

::: demo

<template>
    <mgs-c-view
        style="height: 500px; width: 100%;"
        :view.sync="view"
        :options="options"
        @onMapInited="initMap"
    />
</template>

<script>
export default {
    data() {
        return {
            // 中心点设置（双向绑定）
            view: { center: [108, 40], zoom: 3 },
            // 地图参数
            options: {
                infoBox: false,
                navigation: false,
                sceneModePicker: false
            },
        }
    },
    methods: {
        initMap(bindMap) {
            bindMap.addService(
                '1',
                'arcgisrestmap',
                'https://server.arcgisonline.com/arcgis/rest/services/Specialty/DeLorme_World_Base_Map/MapServer'
            )
        }
    }
}
</script>

:::
</docs>
